package com.songshuai.sales.client.controller;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import com.songshuai.sales.client.service.SalesInfoService;
import com.songshuai.webapi.baseapi.constant.miniprogram.CacheKeys;
import com.songshuai.sales.client.service.WxPlatformService;
import com.songshuai.webapi.baseapi.enumerations.ResultStatus;
import com.songshuai.webapi.baseapi.enumerations.sales.error.SalesInfoError;
import com.songshuai.webapi.baseapi.exception.BusinessException;
import com.songshuai.webapi.baseapi.model.sales.SalesInfo;
import com.songshuai.webapi.baseapi.model.sales.WxPlatform;
import com.songshuai.webapi.baseapi.pojo.QueryResponse;
import com.songshuai.webapi.common.component.WeChatComponent;
import com.songshuai.webapi.common.httpclient.HttpClientUtil;
import com.songshuai.webapi.common.redis.RedisUtil;
import com.songshuai.webapi.common.wechat.WeChatUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Async;
import org.springframework.web.bind.annotation.*;

import java.util.Date;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @Author:wbl
 * @Date: 2019/3/14
 */
@Slf4j
@Api("微信平台")
@RestController
@RequestMapping("/api/sales/platform/")
public class WxPlatformController {

    @Autowired
    private WxPlatformService wxPlatformService;

    @Autowired
    private WeChatComponent weChatComponent;

    @Autowired
    private RedisUtil redisUtil;

    @Autowired
    private SalesInfoService salesInfoService;

    @Value("${pangu.bind.user}")
    private String bindUserUrl;

    @ApiOperation(value = "根据appid获取access_token")
    @PostMapping("getAccessToken")
    public CompletableFuture<QueryResponse> getAccessToken(@RequestParam("appId")String appId){
       return CompletableFuture.supplyAsync(() ->{
           String accessToken = wxPlatformService.getAccessToken(appId);
           return QueryResponse.setResData(accessToken);
       });
    }


    /**
     *1.若该用户是新用户返回未绑定状态  不返回token
     *2.若该用户已经绑定过  直接给token   跳过登录页面
     * @param code
     * @param appid
     * @return
     */
    @ApiOperation(value = "根据js_code获取后端程序token,并判断是否是第一次登录")
    @GetMapping("getToken")
    public CompletableFuture<QueryResponse> getToken(@RequestParam("code")String code,@RequestParam("appid")String appid){
        return  CompletableFuture.supplyAsync(() ->{
        try {
            WxPlatform wxPlatform =getWxPlatform(appid);
            if (null == wxPlatform || StringUtils.isBlank(wxPlatform.getAppSecret())){
                return new QueryResponse(ResultStatus.UNIDENTIFIABLE_APPID_ERROR);
            }
            JSONObject object = weChatComponent.jscode2session(code,appid,wxPlatform.getAppSecret());
            Integer errcode = object.getInteger("errcode");
            String errmsg = object.getString("errmsg");
            log.info("根据code获取openid结果"+object.toJSONString());
            if (null == errcode){
                String openid = object.getString("openid");
                String sessionKey = object.getString("session_key");
                Object o = redisUtil.hget(openid, CacheKeys.OPENID_KEY);
                String token=null;
                //如果redis存在token直接返回给前端  如果没有判断数据库是否绑定过，没有绑定不给token  绑定过跟新绑定token
                if(null!=o){
                    token=(String)o;
                    //异步初始化数据
                    initUserInfoRedis(token,openid,sessionKey);
                    return  QueryResponse.setResData(token);
                }else{
                    SalesInfo salesInfo = salesInfoService.querySalesInfoByOpenId(openid);
                    if(null==salesInfo){
                        return new QueryResponse(ResultStatus.NEED_GET_PERMISSION);
                    }else{
                        token = UUID.randomUUID().toString();
                        redisUtil.hset(token, CacheKeys.OPENID, openid, CacheKeys.TIME_OUT_1);
                        redisUtil.hset(openid,CacheKeys.OPENID_KEY,token,CacheKeys.ONE_DAY);
                        redisUtil.hset(token, CacheKeys.PANGU_USER_ID, salesInfo.getUserId(), CacheKeys.TIME_OUT_1);
                        pushUserTokenToDB(token,0,openid,"",new JSONObject());
                        return QueryResponse.setResData(token);
                    }
                }
            }else {
                return new QueryResponse(ResultStatus.SESSION_KEY_FAILURE);
            }
        } catch (Exception e) {
            log.error("/api/platform/getToken",e);
            return new QueryResponse(ResultStatus.FAIL);
        }
        }).whenComplete((result, throwable) -> {
            if (throwable != null) {
                log.info("获取token异常了"+throwable);
                System.out.println("Unexpected error:"+throwable);
            } else {
                log.info("getToken的结果"+result);
            }

        });
    }



    /**
     * 销售第一次登录销售客户端接口
     */
    @PostMapping("bindSalesUser")
    @ApiOperation(value = "销售第一次登录销售客户端访问接口")
    public CompletableFuture<QueryResponse> bindUser(@RequestParam("code")String code,
                                                     @RequestParam("appid")String appid,
                                                     @RequestParam("username")String username,
                                                     @RequestParam("password")String password,
                                                     @RequestParam("phoneEncryptedData")String phoneEncryptedData,
                                                     @RequestParam("phoneIv")String phoneIv){
        return CompletableFuture.supplyAsync(()->{
            //调用微信接口获取session_key
            WxPlatform wxPlatform =getWxPlatform(appid);
            if (null == wxPlatform || StringUtils.isBlank(wxPlatform.getAppSecret())){
                return new QueryResponse(ResultStatus.UNIDENTIFIABLE_APPID_ERROR);
            }
            JSONObject object = weChatComponent.jscode2session(code,appid,wxPlatform.getAppSecret());
            Integer errcode = object.getInteger("errcode");
            String errmsg = object.getString("errmsg");
            log.info("根据code获取openid和sessionKey返回结果:"+object.toJSONString());
            if (null == errcode){
                String openid = object.getString("openid");
                String sessionKey = object.getString("session_key");
                String   wxResult = WeChatUtil.decrypt(appid,phoneEncryptedData, sessionKey,phoneIv);
                log.info("微信解密手机号结果:"+wxResult);
                //如果不能解密手机号  重新获取登录code
                if(StringUtils.isNotBlank(wxResult)){
                String token = UUID.randomUUID().toString();
                    JSONObject wxResultJson = JSON.parseObject(wxResult);
                    String moblie=wxResultJson.getString("phoneNumber");
                    JSONObject jsonObject = this.getBindUserInfo(username, password, openid, moblie);
                    Integer status=jsonObject.getInteger("status");
                    if(0!=status){
                        return new QueryResponse(ResultStatus.ERROR_BIND_SALES_INFO);
                    }else{
                        if (redisUtil.hset(token, CacheKeys.OPENID, openid, CacheKeys.TIME_OUT_1)){
                            pushUserInfoToRedis(token,jsonObject,openid);
                            pushUserTokenToDB(token,1,openid,moblie,jsonObject);
                            return QueryResponse.setResData(token);
                        }else{
                            return new QueryResponse(ResultStatus.NEED_GET_PERMISSION);
                        }
                    }
                }else{
                    return new QueryResponse(ResultStatus.ERROR_DECRYPT_MOBILE);
                }
            }else {
                return new QueryResponse(ResultStatus.SESSION_KEY_FAILURE);
            }
        });
    }


    //非第一次登录用户  初始化Redis相关值
    @Async
    public void initUserInfoRedis(String token,String openid,String sessionKey){
        Object o = redisUtil.hget(token, CacheKeys.OPENID);
        if(o==null){
            redisUtil.hset(token, CacheKeys.OPENID,openid,CacheKeys.TIME_OUT_1);
            SalesInfo salesInfo = salesInfoService.querySalesInfoByOpenId(openid);
            if(null!=salesInfo) {
                redisUtil.hset(token, CacheKeys.PANGU_USER_ID, salesInfo.getUserId(), CacheKeys.TIME_OUT_1);
            }
        }else{
            redisUtil.expire(token,CacheKeys.TIME_OUT_1);
        }


    }





    //将用户信息放置到redis
    public void pushUserInfoToRedis(String token,JSONObject jsonObject,String openid){
        JSONObject result=jsonObject.getJSONObject("result");
        if(null!=result){
            redisUtil.hset(token, CacheKeys.PANGU_USER_ID, result.getString("UserID"), CacheKeys.TIME_OUT_1);
        }
        redisUtil.hset(openid,CacheKeys.OPENID_KEY,token,CacheKeys.ONE_DAY);
    }


    //将用户token更新至数据库中
    @Async
    public void pushUserTokenToDB(String token,Integer status,String openid,String moblie,JSONObject jsonObject){
        //0:根据openid更新token   1:插入添加新的用户记录
        if(0==status){
            SalesInfo salesInfo =new SalesInfo(){{
                setOpenId(openid);
                setToken(token);
            }};
            salesInfoService.updateSalesInfoByOpenid(salesInfo);
        }else{
            JSONObject result=jsonObject.getJSONObject("result");
            if(null!=result){
                SalesInfo salesInfo =new SalesInfo(){{
                    setIsBind(1);
                    setOpenId(openid);
                    setUserId(result.getString("UserID"));
                    setCreateTime(new Date());
                    setMobile(moblie);
                    setToken(token);
                }};
                salesInfoService.insertSalesInfoForLogin(salesInfo);
            }
        }
    }
    //调用盘古接口绑定
    @HystrixCommand(fallbackMethod="getBindUserInfoFallback")
    public JSONObject getBindUserInfo(String userName,String password,String openId,String moblie){
        JSONObject param=new JSONObject();
        param.put("Account",userName);
        param.put("Password",password);
        param.put("Phone",moblie);
        param.put("OpenId",openId);
        String s = HttpClientUtil.doPostJson(bindUserUrl, param.toJSONString());
        log.info("调用盘古绑定用户信息返回值："+s);
        JSONObject jsonObject = JSONObject.parseObject(s);
        return jsonObject;
    }
    public JSONObject getBindUserInfoFallback(String userName,String password,String openId){
        JSONObject jsonObject = new JSONObject();
        //填写短路保护器相关内容
        jsonObject.put("status",-1);
        jsonObject.put("info","获取用户信息失败");
        jsonObject.put("result","");
        return jsonObject;
    }

    //获取微信平台信息
    public WxPlatform getWxPlatform(String appid){
        Object o= redisUtil.hget(appid,CacheKeys.WXPLATFORM_KEY);
        WxPlatform wxPlatform=null;
        if(null!=o){
            wxPlatform=(WxPlatform)o;
            return wxPlatform;
        }else{
            wxPlatform = wxPlatformService.selectByEntity(new WxPlatform() {{
                setAppId(appid);
            }});
            redisUtil.hset(appid,CacheKeys.WXPLATFORM_KEY,wxPlatform,CacheKeys.ONE_DAY);
            return wxPlatform;
        }
    }

}
